﻿using StackExchange.Redis;
using System.Text.Json;

namespace VerEasy.Core.Extensions.Caching.Redis
{
    public class RedisCache(IConnectionMultiplexer connectionMultiplexer) : IRedisCache
    {
        private readonly IDatabase redis = connectionMultiplexer.GetDatabase();
        private readonly IConnectionMultiplexer connectionMultiplexer = connectionMultiplexer;

        public void Clear()
        {
            var endpoints = connectionMultiplexer.GetEndPoints();
            foreach (var endpoint in endpoints)
            {
                var server = connectionMultiplexer.GetServer(endpoint);
                foreach (var key in server.Keys())
                {
                    redis.KeyDelete(key);
                }
            }
        }

        public async Task ClearAsync()
        {
            //Gets all endpoints defined on the multiplexer.
            var endpoints = connectionMultiplexer.GetEndPoints();
            var tasks = endpoints.Select(async x =>
            {
                var server = connectionMultiplexer.GetServer(x);
                foreach (var key in server.Keys())
                {
                    await redis.KeyDeleteAsync(key);
                }
            });

            await Task.WhenAll(tasks);
        }

        public bool Exists(string key)
        {
            return redis.KeyExists(key);
        }

        public async Task<bool> ExistsAsync(string key)
        {
            return await redis.KeyExistsAsync(key);
        }

        public string Get(string key)
        {
            return redis.StringGet(key);
        }

        public async Task<string> GetAsync(string key)
        {
            return await redis.StringGetAsync(key);
        }

        public void Remove(string key)
        {
            redis.KeyDelete(key);
        }

        public async Task RemoveAsync(string key)
        {
            await redis.KeyDeleteAsync(key);
        }

        public void Set(string key, object value, TimeSpan? expirationTime = null)
        {
            if (value != null)
            {
                //默认2H
                expirationTime ??= TimeSpan.FromHours(2);
                if (value is string cacheStr)
                {
                    redis.StringSet(key, cacheStr, expirationTime);
                }
                else
                {
                    redis.StringSet(key, JsonSerializer.Serialize(value), expirationTime);
                }
            }
        }

        public async Task SetAsync(string key, object value, TimeSpan? expirationTime = null)
        {
            if (value != null)
            {
                //默认2H
                expirationTime ??= TimeSpan.FromHours(2);
                if (value is string cacheStr)
                {
                    await redis.StringSetAsync(key, cacheStr, expirationTime);
                }
                else
                {
                    await redis.StringSetAsync(key, JsonSerializer.Serialize(value), expirationTime);
                }
            }
        }
    }
}